 /* 
 * Copyright 2013 Dominik Korittki, Steffen Gruschka

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

package beans;

import ejb.EJBManager;
import entity.Mitarbeiter;
import entity.Raum;
import java.util.ArrayList;
import java.util.List;
import javax.ejb.EJB;
import javax.ejb.EJBException;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.model.SelectItem;
import javax.transaction.RollbackException;
import javax.transaction.SystemException;


/**
 * Bean für die Mitarbeiterverwaltungsseiten.
 * Diese Klasse ist neben der RaeumeverwaltungsBean hautsächlich für die Logik 
 * des Systems verantwortlich.
 * @author Dominik K.
 * @author Steffen G.
 */
@ManagedBean(name = "mitarbeiterverwaltung")
@SessionScoped
public class MitarbeiterVerwaltungBean {
    /**
     * Pfad zur Mitarbeiter-hinzufügen Seite
     */
    private final static String MITARBEITERHINZUFUEGEN = "./mitarbeiteranlegen.xhtml?faces-redirect=true";
    /**
     * Pfad zur Mitarbeiter-bearbeiten Seite
     */
    private final static String MITARBEITERBEARBEITEN = "./mitarbeiterbearbeiten.xhtml?faces-redirect=true";
    /**
     * Pfad zur Mitarbeiterverwaltung Seite
     */
    private final static String MITARBEITERVERWALTUNG = "./mitarbeiterverwaltung.xhtml?faces-redirect=true";
    /**
     * Pfad zur zentralen Verwaltung
     */
    private final static String VERWALTUNG = "../index.xhtml?faces-redirect=true";
    /**
     * EJB für JPA Logik
     */
    @EJB
    private EJBManager ejbm;
    /**
     * Parameter für das Paging von Tabellen
     */
    private int first;
    /**
     * Mitarbeiter Objekt, welches die Seiten zur Datenspeicherung benutzen
     */
    private Mitarbeiter mitarbeiter = new Mitarbeiter();
    /**
     * Alle Räume, die als Checkboxen zum Eintragen zur Auswahl stehen
     */
    private List<SelectItem> raeumeCheckboxen = new ArrayList<SelectItem>();
    /**
     * IDs der Räume, die in den Checkboxen ausgewählt wurden
     */
    private List<String> selectedItems = new ArrayList<String>();
    /**
     * Falls Fehler angezeigt werden und der Benutzer-Input nicht verloren gehen soll
     */
    private boolean formInputBehalten = false;
    
    /**
     * Generiert eine Instanz
     */
    public MitarbeiterVerwaltungBean() {
    }
    
    
    /**
     * Gibt das First-Objekt zurück
     * @return first Objekt
     */
    public int getFirst() {
        return this.first;
    }

    /**
     * Setzt das first Objekt
     * @param first neues first Objekt
     */
    public void setFirst(int first) {
        this.first = first;
    }
    
    /**
     * Liefert das Mitarbeiter Objekt
     * @return das Mitarbeiter Objekt
     */
    public Mitarbeiter getMitarbeiter() {
        return mitarbeiter;
    }
    
    /**
     * Setzt ein neues Mitarbeiter Objekt
     * @param mitarbeiter neues Mitarbeiter Objekt
     */
    public void setMitarbeiter(Mitarbeiter mitarbeiter) {
        this.mitarbeiter = mitarbeiter;
    }
    
    /**
     * Liefert das selected-Items Objekt
     * @return das selected-Items Objekt
     */
    public List<String> getSelectedItems() {
        return selectedItems;
    }

    /**
     * Setzt ein neues selectedItems Objekt
     * @param selectedItems Das neue selectedItems Objekt
     */
    public void setSelectedItems(List<String> selectedItems) {
        this.selectedItems = selectedItems;
    }

    /**
     * Liefert das raeumeCheckboxen Ojekt
     * @return das raeumeCheckboxen Objekt
     */
    public List<SelectItem> getRaeumeCheckboxen() {
        return raeumeCheckboxen;
    }

    /**
     * Setzt ein neues raeumeCheckboxen Objekt
     * @param raeumeCheckboxen Neues Objekt
     */
    public void setRaeumeCheckboxen(List<SelectItem> raeumeCheckboxen) {
        this.raeumeCheckboxen = raeumeCheckboxen;
    }
    
    /**
     * Liest alle Mitarbeiter aus der Datenbank und gibt diese als Liste zurück
     * @return Liste aller Mitarbeiter
     */
    public List<Mitarbeiter> getMitarbeiterListe() {
        try {
            return ejbm.getMitarbeiter();
        } catch(EJBException e) {
            exceptionHandler(e);
            return new ArrayList<Mitarbeiter>();
        }
    }
    
    /**
     * Kann von Commandbuttons oder Links als Weiterleitungsadresse benutzt werden
     * @return Pfad zur Mitarbeiter-anlegen Seite
     */
    public String zuMitarbeiterAnlegen() {
        return MITARBEITERHINZUFUEGEN;
    }
    
    /**
     * Kann von Commandbuttons oder Links als Weiterleitungsadresse benutzt werden.
     * Die bereits ausgewählten Räume werden wieder vorselektiert
     * @param m Zu bearbeitender Mitarbeiter
     * @return Pfad zur Mitarbeiter-bearbeiten Seite
     */
    public String zuMitarbeiterBearbeiten(Mitarbeiter m) {
        mitarbeiter = m;
        selectedItems.clear();
        raeumeCheckboxen.clear();
        for(Raum r : ejbm.getRaeume()) {
            SelectItem sItem = new SelectItem(r.getId(), r.getName());
            if(r.getBefugte().contains(mitarbeiter)) {
                selectedItems.add(r.getId().toString()); //Vorselektion
            }
            getRaeumeCheckboxen().add(sItem);
        }
        return MITARBEITERBEARBEITEN;
    }
    
    /**
     * Kann von Commandbuttons oder Links als Weiterleitungsadresse benutzt werden
     * @return Pfad zur Mitarbeiter-verwaltung Seite
     */
    public String zuMitarbeiterVerwaltung() {
        return MITARBEITERVERWALTUNG;
    }
    
    /**
     * Kann von Commandbuttons oder Links als Weiterleitungsadresse benutzt werden
     * @return Pfad zur Verwaltungs Seite
     */
    public String zuVerwaltung() {
        return VERWALTUNG;
    }
    
    /**
     * Persistiert einen Mitarbeiter sowie die Beziehungen zu Räumen
     * @return Pfad zur Verwaltungsseite oder null, 
     * falls eine Fehlernachricht angezeigt werden soll
     */
    public String mitarbeiterHinzufuegen() {
        try {
            ejbm.persist(mitarbeiter);
            //Eintraege parsen
            //mitarbeiter.setVorname(Parser.keineUmlaute(mitarbeiter.getVorname()));
            //mitarbeiter.setNachname(Parser.keineUmlaute(mitarbeiter.getNachname()));
            //Alle ausgewählten Räume als neue Beziehung hinzufügen
            for(String s : selectedItems) {
                Raum r = ejbm.findeRaum(new Long(s));
                mitarbeiter.raumHinzufuegen(r);
                r.befugtenHinzufuegen(mitarbeiter);
                ejbm.merge(r);
            }
            //ejbm.persist(mitarbeiter);
            ejbm.merge(mitarbeiter);
            mitarbeiter = new Mitarbeiter();
            selectedItems.clear();
            raeumeCheckboxen.clear();
        } catch(EJBException e) {
            exceptionHandler(e);
            formInputBehalten = true;
            return null;
        }
        return MITARBEITERVERWALTUNG;
    }
    
    /**
     * Aktualisiert die Informationen eines Mitarbeiters.
     * @return Pfad zur Bearbeiten Seite oder null, 
     * falls eine Fehlernachricht angezeigt werden soll
     */
    public String mitarbeiterBearbeiten() {
        //Zunächst alle Beziehungen von dem Mitarbeiter zu seinen Räumen löschen
        mitarbeiter.alleRaeumeEntfernen();
        try {
            for(Raum r : ejbm.getRaeume()) {
                r.befugtenEntfernen(mitarbeiter);
                ejbm.merge(r);
            }
            
            //Alle ausgewählten Räume jetzt wieder als neue Beziehung hinzufügen
            for(String s : selectedItems) {
                Raum r = ejbm.findeRaum(new Long(s));
                mitarbeiter.raumHinzufuegen(r);
                r.befugtenHinzufuegen(mitarbeiter);
                ejbm.merge(r);
            }
            
            //Datenbankpersistierung
            ejbm.merge(mitarbeiter);
            
            //Werte zuruecksetzen
            mitarbeiter = new Mitarbeiter();
            selectedItems.clear();
            raeumeCheckboxen.clear();
        } catch(EJBException e) {
            exceptionHandler(e);
            formInputBehalten = true;
            return null;
        } finally {
            return MITARBEITERVERWALTUNG;
        }
    }
    
    /**
     * Löscht einen Mitarbeiter aus der DB
     * @param m Zu löschender Mitarbeiter
     * @return Pfad zur Mitarbeiterverwaltung oder null,
     * falls eine Fehlernachricht angezeigt werden muss
     */
    public String mitarbeiterLoeschen(Mitarbeiter m) {
        try {
            ejbm.remove(m);
            return MITARBEITERVERWALTUNG;
        } catch(EJBException e) {
            exceptionHandler(e);
            return null;
        }
    }
    
    /**
     * Setzt alle Attribute des gemerkten Mitarbeiterobjekts zurück, sowie Checkboxinfomationen
     * sodass keine alten Informationen in den Formularen angezeigt werden
     */
    public void attributeZuruecksetzen() {
        if(formInputBehalten) {
            formInputBehalten = false;
            Mitarbeiter temp = mitarbeiter;
            mitarbeiter = new Mitarbeiter();
            mitarbeiter.setKennkartenNr(temp.getKennkartenNr());
            mitarbeiter.setVorname(temp.getVorname());
            mitarbeiter.setNachname(temp.getNachname());
            mitarbeiter.setRaeume(mitarbeiter.getRaeume());
            return;
        }
        mitarbeiter = new Mitarbeiter();
        selectedItems.clear();
        raeumeCheckboxen.clear();
        for(Raum r : ejbm.getRaeume()) {
            SelectItem sItem = new SelectItem(r.getId(), r.getName());
            raeumeCheckboxen.add(sItem);
        }
    }
    
    /**
     * Terminiert die Session des zurzeit eingelogten Benutzers
     * @param nutzer Aktuell eingeloggter Nutzer
     * @return Link zur Verwaltungsstartseite, sichtbar ist aufgrund der
     * terminierten Session allerdings die Loginseite
     */
    public String logout(SessionNutzer nutzer) {
        SessionNutzer.logout(nutzer);
        return VERWALTUNG;
    }
    
    /**
     * Paging Funktion zum Weiterblättern
     */
    public void weiter() {
        first = first + 10;
        if (first == ejbm.getMitarbeiter().size()) {
            first = ejbm.getMitarbeiter().size() - 10;
        }
    }

    /**
     * Paging Funktion zum Zurückblättern
     */
    public void zurueck() {
        first = first - 10;
        if (first <= 0) {
            first = 0;
        }
    }

    /**
     * Paging-Funktion um zu entscheiden ob der zurück-Link angezeigt werden soll
     * @return Link anzeigen oder nicht
     */
    public boolean zurueckVisible() {
        if (first >= 10) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * Paging-Funktion um zu entscheiden ob der weiter-Link angezeigt werden soll
     * @return Link anzeigen oder nicht
     */
    public boolean weiterVisible() {
        if (ejbm.getMitarbeiter().size() > first+10) {
            return true;

        } else {
            return false;
        }
    }
    
    /**
     * Paging-Funktion, die die Anzahl der Seiten anzeigt
     * @return Anzahl der Seiten
     */
    public String pageCounter() {
        return Integer.toString(first / 10 + 1);
    }
    
    /**
     * Gibt an ob Mitarbeiter vorhanden sind
     * @return true falls es Mitarbeiter gibt, false falls nein
     */
    public boolean mitarbeiterVorhanden() {
        return getMitarbeiterListe().isEmpty();
    }

    /**
     * Analysiert die EJBException und generiert Fehlernachrichten für die JSF-Seiten
     * @param e EJBException, welche von der EJB geschmissen wurde
     */
    private void exceptionHandler(EJBException e) {
        if(e.getCausedByException() instanceof SystemException) {
            FacesContext facesContext = FacesContext.getCurrentInstance();
            FacesMessage facesMessage = new FacesMessage(FacesMessage.SEVERITY_ERROR,
                    "Die Datenbank ist nicht erreichbar",
                    "Konnte keine Verbindung mit der Datenbank aufbauen");
            facesContext.addMessage(null, facesMessage);
        } else if(e.getCausedByException() instanceof RollbackException) {
            FacesContext facesContext = FacesContext.getCurrentInstance();
            FacesMessage facesMessage = new FacesMessage(FacesMessage.SEVERITY_ERROR,
                    "Nummer bereits vorhanden, bitte Anderen wählen",
                    "Es gibt bereits einen Eintrag mit diesem Namen");
            facesContext.addMessage(null, facesMessage);
        } else if(e.getCausedByException() instanceof IllegalArgumentException) {
            FacesContext facesContext = FacesContext.getCurrentInstance();
            FacesMessage facesMessage = new FacesMessage(FacesMessage.SEVERITY_ERROR,
                    "Datenbankeintrag nicht vorhanden",
                    "Konnte den benötigten DB-Eintrag nicht finden");
            facesContext.addMessage(null, facesMessage);
        } else {
            FacesContext facesContext = FacesContext.getCurrentInstance();
            FacesMessage facesMessage = new FacesMessage(FacesMessage.SEVERITY_ERROR,
                    "Es ist ein unbekannter Fehler aufgetreten",
                    "Unbekannter Fehler aufgetreten: " + e.getMessage());
            facesContext.addMessage(null, facesMessage);
        }
    }
}
